From 8533ad9cf6d2c173059d90582469cb6c693524e6 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Tue, 6 Jul 2004 15:21:43 +0000 Subject: [PATCH] bitkeeper revision 1.1041.9.1 (40eac387W39rUFRFKTwvCfPBOF7Aow) Convert most 'xm create' command-line switches to variables. --- tools/python/xen/util/ip.py | 53 +++++++++++++++----- tools/python/xen/xm/create.py | 69 ++++++++++++-------------- tools/python/xen/xm/opts.py | 93 ++++++++++++++++++++++++++++++----- 3 files changed, 155 insertions(+), 60 deletions(-) diff --git a/tools/python/xen/util/ip.py b/tools/python/xen/util/ip.py index 8396e0d014..39eb01f944 100644 --- a/tools/python/xen/util/ip.py +++ b/tools/python/xen/util/ip.py @@ -3,7 +3,7 @@ import re import socket import struct -def readlines(fd): +def _readlines(fd): """Version of readlines safe against EINTR. """ import errno @@ -21,7 +21,7 @@ def readlines(fd): lines.append(line) return lines -def readline(fd): +def _readline(fd): """Version of readline safe against EINTR. """ while 1: @@ -42,11 +42,14 @@ as it may have been moved onto the bridge. NBE_BRIDGE = 'nbe-br' def get_current_ipaddr(dev='eth0'): - """Return a string containing the primary IP address for the given - network interface (default 'eth0'). + """Get the primary IP address for the given network interface. + + dev network interface (default eth0) + + returns interface address as a string """ fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' ) - lines = readlines(fd) + lines = _readlines(fd) for line in lines: m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*', line ) @@ -57,11 +60,14 @@ def get_current_ipaddr(dev='eth0'): return None def get_current_ipmask(dev='eth0'): - """Return a string containing the primary IP netmask for the given - network interface (default 'eth0'). + """Get the primary IP netmask for a network interface. + + dev network interface (default eth0) + + returns interface netmask as a string """ fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' ) - lines = readlines(fd) + lines = _readlines(fd) for line in lines: m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*', line ) @@ -72,11 +78,14 @@ def get_current_ipmask(dev='eth0'): return None def get_current_ipgw(dev='eth0'): - """Return a string containing the IP gateway for the given - network interface (default 'eth0'). + """Get the IP gateway for a network interface. + + dev network interface (default eth0) + + returns gateway address as a string """ fd = os.popen( '/sbin/route -n' ) - lines = readlines(fd) + lines = _readlines(fd) for line in lines: m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' + '\s+\S+\s+\S*G.*' + dev + '.*', line ) @@ -88,24 +97,46 @@ def get_current_ipgw(dev='eth0'): def inet_aton(addr): """Convert an IP addr in IPv4 dot notation into an int. + + addr IP address as a string + + returns integer """ b = socket.inet_aton(addr) return struct.unpack('!I', b)[0] def inet_ntoa(n): """Convert an int into an IP addr in IPv4 dot notation. + + n IP address + + returns string """ b = struct.pack('!I', n) return socket.inet_ntoa(b) def add_offset_to_ip(addr, offset): """Add a numerical offset to an IP addr in IPv4 dot notation. + + addr IP address + offset offset to add + + returns new address """ n = inet_aton(addr) n += offset return inet_ntoa(n) def check_subnet( ip, network, netmask ): + """Check if an IP address is in the subnet defined by + a network address and mask'. + + ip IP adress + network network address + netmask network mask + + returns 1 if it is in the subnet, 0 if not + """ n_ip = inet_aton(ip) n_net = inet_aton(network) n_mask = inet_aton(netmask) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 3c61db9325..cf82d075f9 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -13,7 +13,7 @@ from xen.util import console_client from xen.xm.opts import * -gopts = Opts(use="""[options] +gopts = Opts(use="""[options] [vars] Create a domain. @@ -66,54 +66,49 @@ gopts.opt('load', short='L', val='FILE', fn=set_value, default=None, use='Domain saved state to load.') -#gopts.opt('define', short='D', val='VAR=VAL', -# fn=set_var, default=None, -# use="""Set a variable before loading defaults, e.g. '-D vmid=3' -# to set vmid. May be repeated to set more than one variable.""") - gopts.opt('dryrun', short='n', fn=set_true, default=0, use="""Dry run - print the config but don't create the domain. The defaults file is loaded and the SXP configuration is created and printed. """) -gopts.opt('name', short='N', val='NAME', - fn=set_value, default=None, - use="Domain name.") - gopts.opt('console_autoconnect', short='c', fn=set_true, default=0, use="Connect to console after domain is created.") -gopts.opt('kernel', short='k', val='FILE', +gopts.var('name', val='NAME', + fn=set_value, default=None, + use="Domain name.") + +gopts.var('kernel', val='FILE', fn=set_value, default=None, use="Path to kernel image.") -gopts.opt('ramdisk', short='r', val='FILE', +gopts.var('ramdisk', val='FILE', fn=set_value, default='', use="Path to ramdisk.") -gopts.opt('builder', short='b', val='FUNCTION', +gopts.var('builder', val='FUNCTION', fn=set_value, default='linux', use="Function to use to build the domain.") -gopts.opt('memory', short='m', val='MEMORY', +gopts.var('memory', val='MEMORY', fn=set_value, default=128, use="Domain memory in MB.") -gopts.opt('autorestart', - fn=set_true, default=0, +gopts.var('autorestart', val='no|yes', + fn=set_bool, default=0, use="Whether to restart the domain on exit.") -gopts.opt('blkif', - fn=set_true, default=0, +gopts.var('blkif', val='no|yes', + fn=set_bool, default=0, use="Make the domain a block device backend.") -gopts.opt('netif', - fn=set_true, default=0, +gopts.var('netif', val='no|yes', + fn=set_bool, default=0, use="Make the domain a network interface backend.") -gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE', +gopts.var('disk', val='phy:DEV,VDEV,MODE', fn=append_value, default=[], use="""Add a disk device to a domain. The physical device is DEV, which is exported to the domain as VDEV. The disk is read-only if MODE @@ -121,18 +116,18 @@ gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE', The option may be repeated to add more than one disk. """) -gopts.opt('pci', val='BUS,DEV,FUNC', +gopts.var('pci', val='BUS,DEV,FUNC', fn=append_value, default=[], use="""Add a PCI device to a domain, using given params (in hex). For example '-pci c0,02,1a'. The option may be repeated to add more than one pci device. """) -gopts.opt('ipaddr', short='i', val="IPADDR", +gopts.var('ipaddr', val="IPADDR", fn=append_value, default=[], use="Add an IP address to the domain.") -gopts.opt('vif', val="mac=MAC,bridge=BRIDGE", +gopts.var('vif', val="mac=MAC,bridge=BRIDGE", fn=append_value, default=[], use="""Add a network interface with the given MAC address and bridge. If mac is not specified a random MAC address is used. @@ -141,7 +136,7 @@ gopts.opt('vif', val="mac=MAC,bridge=BRIDGE", Specifying vifs will increase the number of interfaces as needed. """) -gopts.opt('nics', val="NUM", +gopts.var('nics', val="NUM", fn=set_int, default=1, use="""Set the number of network interfaces. Use the vif option to define interface parameters, otherwise @@ -149,44 +144,44 @@ gopts.opt('nics', val="NUM", number of interfaces as needed. """) -gopts.opt('root', short='R', val='DEVICE', +gopts.var('root', val='DEVICE', fn=set_value, default='', use="""Set the root= parameter on the kernel command line. Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""") -gopts.opt('extra', short='E', val="ARGS", +gopts.var('extra', val="ARGS", fn=set_value, default='', use="Set extra arguments to append to the kernel command line.") -gopts.opt('ip', short='I', val='IPADDR', +gopts.var('ip', val='IPADDR', fn=set_value, default='', use="Set the kernel IP interface address.") -gopts.opt('gateway', val="IPADDR", +gopts.var('gateway', val="IPADDR", fn=set_value, default='', use="Set the kernel IP gateway.") -gopts.opt('netmask', val="MASK", +gopts.var('netmask', val="MASK", fn=set_value, default = '', use="Set the kernel IP netmask.") -gopts.opt('hostname', val="NAME", +gopts.var('hostname', val="NAME", fn=set_value, default='', use="Set the kernel IP hostname.") -gopts.opt('interface', val="INTF", +gopts.var('interface', val="INTF", fn=set_value, default="eth0", use="Set the kernel IP interface name.") -gopts.opt('dhcp', val="off|dhcp", +gopts.var('dhcp', val="off|dhcp", fn=set_value, default='off', use="Set the kernel dhcp option.") -gopts.opt('nfs_server', val="IPADDR", +gopts.var('nfs_server', val="IPADDR", fn=set_value, default=None, use="Set the address of the NFS server for NFS root.") -gopts.opt('nfs_root', val="PATH", +gopts.var('nfs_root', val="PATH", fn=set_value, default=None, use="Set the path of the root NFS directory.") @@ -315,7 +310,7 @@ def preprocess_vifs(opts): d = {} a = vif.split(',') for b in a: - (k, v) = b.strip().split('=') + (k, v) = b.strip().split('=', 1) k = k.strip() v = v.strip() if k not in ['mac', 'bridge']: @@ -392,7 +387,7 @@ def main(argv): # Process remaining args as config variables. for arg in args: if '=' in arg: - (var, val) = arg.strip().split('=') + (var, val) = arg.strip().split('=', 1) gopts.setvar(var.strip(), val.strip()) if opts.vals.config: pass diff --git a/tools/python/xen/xm/opts.py b/tools/python/xen/xm/opts.py index 25f11abad2..4f963b5146 100644 --- a/tools/python/xen/xm/opts.py +++ b/tools/python/xen/xm/opts.py @@ -126,6 +126,42 @@ class Opt: """ return self.specified_opt +class OptVar(Opt): + """An individual option variable. + """ + def __init__(self, opts, name, + val=None, fn=None, use=None, default=None): + """Create an option. + + opts parent options object + name name of the field it controls + val string used to print option args in help. + If val is not specified the option has no arg. + fn function to call when the option is specified. + use usage (help) string + default default value if not specified on command-line + """ + if val is None: + val = name.upper() + Opt.__init__(self, opts, name, val=val, fn=fn, use=use, default=default) + self.optkeys = [] + self.optkeys.append(self.long) + + def short_opt(self): + return None + + def long_opt(self): + return None + + def show(self): + print '%s=%s' %(self.optkeys[0], self.val) + print + if self.use: + print '\t', + print self.use + if self.val: + print '\tDefault', self.default or 'None' + class OptVals: """Class to hold option values. """ @@ -134,6 +170,13 @@ class OptVals: class Opts: """Container for options. """ + + imports = ["import sys", + "import os", + "import os.path", + "from xen.util.ip import *", + ] + def __init__(self, use=None): """Options constructor. @@ -168,6 +211,12 @@ class Opts: self.options_map[name] = x return x + def var(self, name, **args): + x = OptVar(self, name, **args) + self.options.append(x) + self.options_map[name] = x + return x + def setvar(self, var, val): """Set a default script variable. """ @@ -232,7 +281,14 @@ class Opts: else: print >>sys.stderr, "Error: Unknown option:", k self.usage() - return args + xargs = [] + for arg in args: + (k, v) = arg.split('=', 1) + for opt in self.options: + if opt.specify(k, v): break + else: + xargs.append(arg) + return xargs def short_opts(self): """Get short options specifier for getopt. @@ -257,6 +313,7 @@ class Opts: def usage(self): print 'Usage: ', self.argv[0], self.use or 'OPTIONS' for opt in self.options: + print opt.show() def load_defaults(self, help=0): @@ -287,21 +344,22 @@ class Opts: globals = {} locals = {} locals.update(self.vars) - cmd = '\n'.join(["import sys", - "import os", - "import os.path", - "from xen.xm.help import Vars", - "from xen.util import ip", - "xm_file = '%s'" % defaults, - "xm_help = %d" % help, - "xm_vars = Vars(xm_file, xm_help, locals())", - ]) + cmd = '\n'.join(self.imports + + [ "from xen.xm.help import Vars", + "xm_file = '%s'" % defaults, + "xm_help = %d" % help, + "xm_vars = Vars(xm_file, xm_help, locals())" + ]) exec cmd in globals, locals try: execfile(defaults, globals, locals) except: if not help: raise - if help: return + if help: + print 'The following imports are done automatically:' + for x in self.imports: + print x + return # Extract the values set by the script and set the corresponding # options, if not set on the command line. vtypes = [ types.StringType, @@ -322,6 +380,17 @@ def set_false(opt, k, v): """Set an option false.""" opt.set(0) +def set_bool(opt, k, v): + """Set a boolean option. + """ + if v in ['yes']: + opt.set(1) + elif v in ['no']: + opt.set(0) + else: + opt.opts.err('Invalid value:' +v) + + def set_value(opt, k, v): """Set an option to a valoue.""" opt.set(v) @@ -341,6 +410,6 @@ def append_value(opt, k, v): def set_var(opt, k, v): """Set a default script variable. """ - (var, val) = v.strip().split('=') + (var, val) = v.strip().split('=', 1) opt.opts.setvar(var.strip(), val.strip()) -- 2.30.2